'''
Created on Aug 1, 2013

@author: abishop
'''
############################################################################
# A sample program to create a single-track MIDI file, add a note,
# and write to disk.
############################################################################

#Import the library


from music import GUI
from music import MusicSheetGUI
from tkinter import *
root = GUI.Tk()
interface = GUI.GUI(root)
root.mainloop()
root.destroy()
#print(root.user_input)
print(interface.song_melody_list)




from midiutil.MidiFile3 import MIDIFile
import random
# Create the MIDIFile Object
MyMIDI = MIDIFile(1)

# Add track name and tempo. The first argument to addTrackName and
# addTempo is the time to write the event.
track = 0
time = 0
channel = 0
pitch = 60
duration = interface.user_input[3]*4
volume = interface.user_input[2]
repeats=interface.user_input[1]
MyMIDI.addTrackName(track,time,interface.user_input[0])
MyMIDI.addTempo(track,time, 120)
scale={"c": 0, "d":2, "e":4, "f":6, "g":7,"a":9, "b":11}

Triads=[["a", "c", "e"], ["a", "c", "f"], ["g", "c", "e"], ["a", "d", "f"], ["g", "b", "e"], ["g", "b", "d"], ["b", "d", "f"]]

Instruments={'piano':0, 'harpsichord':6, 'glock':9, 'vibes':11,
                            'marimba':12, 'organ':19, 'guitar':24, 'bass':32,
                            'violin':40, 'cello':42, 'harp':46, 'timps':47,
                            'voice':54, 'trumpet':56, 'tuba':58, 'horn':60,
                            'alto sax': 65, 'oboe':68, 'bassoon':70, 'clarinet':71,
                            'flute':73, 'recorder':74, 'bottle':75, 'whistle':78,
                            'fifths':96, 'halo':94, 'goblins':101, 'koto':107,
                            'bagpipe':109, 'taiko':116, 'toms':117, 'breath':121,
                            'seashore':122, 'bird':123, 'phone':124, 'applause':126}
def findTriads(note):
    triads=[]
    for j in Triads:
        if j.count(note.letter)==1:
            triads.append(j)
    return triads

def pickTriads(lists):
    num=random.randint(0,2)
    return lists[num]

class Note:
    def __init__(self, letter, length):
        self.letter=letter
        self.duration=length
        self.raw_value=scale[letter]
        self.voice=72
        self.value=self.raw_value+self.voice

#create a series of triads based on the given tune
Melody=interface.song_melody_list
Tune=[]
for i in Melody:
    if len(i)>1:
        Tune.append( Note(i[0], 4/int(i[1:]) ) )
    else: Tune.append( Note(i, duration))
TriadList=[]

for i in Tune:
    possibleTriads=findTriads(i)
    TriadList.append(pickTriads(possibleTriads))

class Voice:
    def __init__(self, place, shift):
        self.place=place
        self.notes=[]
        self.shift=shift
    
    def makeHarmony(self, TriadList):
        for notePos in range(len(TriadList)):
            triad=[]
            for i in TriadList[notePos]:
                triad.append(scale[i])
            check=''
            balance=[]
            notesUsed=getOthers(notePos, self.place)
            if len(triad)==1:
                choice=0
                check+="too short"
            else:
                for i in notesUsed:
                    if notesUsed.count(i)==2 and i in triad:
                        triad.remove(i)
                        check+="used"
                    if notesUsed.count(i)==1 and self.place==4 and len(triad)>1 and i in triad:
                        triad.remove(i)
                if self.notes==[]:
                    check+="empty"
                    choice=random.randint(0,len(triad)-1)
                else:
                    for j in triad:
                        if self.notes[notePos-1]-self.shift-j<2 and self.notes[notePos-1]>self.shift+j:
                            balance.append(j)
                        elif self.shift+j-self.notes[notePos-1]<2 and self.notes[notePos-1]<self.shift+j:
                            balance.append(j)
                    triad.extend(balance)
                    choice=random.randint(0,len(triad)-1)
            self.notes.append(self.shift+int(triad[choice]))
            



        
soprano=Voice(1, 72)
alto=Voice(2, 60)
tenor=Voice(3, 48)
bass=Voice(4, 36)



for i in Tune:
    i.voice=soprano.shift
    soprano.notes.append(i)

def getOthers(loc, voice):
    notes=[]
    if voice>=2:
        notes.append(soprano.notes[loc].raw_value)
    if voice>=3:
        notes.append(alto.notes[loc]-alto.shift)
    if voice>=4:
        notes.append(tenor.notes[loc]-tenor.shift)
    return notes


alto.makeHarmony(TriadList)
tenor.makeHarmony(TriadList)
bass.makeHarmony(TriadList)

print(soprano.notes)
print(alto.notes)
print(tenor.notes)
print(bass.notes)
# Add a note. addNote expects the following information:


# Now add the note.
time=0
for channel in range(0,3):
        MyMIDI.addProgramChange(0, channel, 0, Instruments[interface.user_input[4]])
loop=0
sopranoList=[[]]
while loop<repeats:
    for i in range(len(Tune)):
        MyMIDI.addNote(track,channel,soprano.notes[i].value,time, Tune[i].duration,volume)
#     if time%2==0 or Tune[i].duration>=2:
        MyMIDI.addNote(track,channel+1,alto.notes[i],time,Tune[i].duration,volume)
        MyMIDI.addNote(track,channel+2,tenor.notes[i],time,Tune[i].duration,volume)
        MyMIDI.addNote(track,channel+3,bass.notes[i],time,Tune[i].duration,volume)
        time+=Tune[i].duration
    loop+=1
    for i in soprano.notes:
        sopranoList[0].append(i.value)
# And write it to disk.
binfile = open(interface.user_input[0]+".mid", 'wb')
MyMIDI.writeFile(binfile)
binfile.close()

x=90

MusicSheetGUI.makeSheet(sopranoList)

